﻿using System;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;

namespace NUnit4PowerShell
{
    static public class Utils
    {

        static public string GetDllConfigurationFileName()
        {
            return "NUnit4PowerShell.config";// "NUnit4PowerShell.config";
        }

        static public string GetPSFixtureNamePattern()
        {
            string namePattern = GetDllConfigurationValue("PSFixtureNamePattern");

            if (string.IsNullOrEmpty(namePattern))
            {
                throw new ArgumentException(
                    string.Format("The setting 'PSFixtureNamePattern' in the configuration file has not been filled. Check {0}",
                                  AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
            }

            return namePattern;
        }

        static public string GetPSTestFunctionNamePattern()
        {
            string namePattern = GetDllConfigurationValue("PSTestFunctionNamePattern");
            if (string.IsNullOrEmpty(namePattern))
            {
                throw new ArgumentException(
                    string.Format("The setting 'PSTestFunctionNamePattern' in the configuration file has not been filled. Check {0}",
                                  AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
            }

            return namePattern;
        }

        static public string GetMockCmdLetScriptPath()
        {
            return GetFileFullPath("CmdLetMocksScript", false);
        }

        static public string GetFilePath(string fileName)
        {
            if (fileName == null)
            {
                return null;
            }
            string fullPath;
            if (!File.Exists(fileName))
            {
                // If the file doesn't exist with check specificly inside the folder defined above
                fullPath = System.IO.Path.Combine(Utils.GetPSFixturesFolderPath(), fileName);
                if (!File.Exists(fullPath))
                {
                    throw new FileNotFoundException(
                        string.Format(
                            "File containing tests to execute can not be found at the path indicated in the key '{0}' in {1}",
                            fileName,
                            AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
                }
            }
            else
            {
                fullPath = System.IO.Path.GetFullPath(fileName);
            }
            return fullPath;
        }

        static public string GetPSFixturesFolderPath()
        {
            // Folder path containing the file to tests -> used for ls in PowerShell
            string folderPath = GetDllConfigurationValue("FolderPath");
            if (string.IsNullOrEmpty(folderPath))
            {
                // If field is not filled : we use dll current directory
                folderPath = GetNUnit4PowerShellDirectory();
            }

            if (!Directory.Exists(folderPath))
            {
                folderPath = Path.Combine(GetNUnit4PowerShellDirectory(), folderPath);
            }

            if (!Directory.Exists(folderPath))
            {
                throw new FileNotFoundException(
                    string.Format("Folder containing the test file to execute can not be found at the path indicated in the key 'TestFileFolderPath' in {0}",
                                  AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
            }

            return System.IO.Path.GetFullPath(folderPath);
        }

        static public string[] GetPSFixtureFiles()
        {
            var folder = Utils.GetPSFixturesFolderPath();
            string[] files = Directory.GetFiles(folder, Utils.GetPSFixtureNamePattern(),
                                                SearchOption.AllDirectories);


            if (files.Length == 0)
            {
                throw new FileNotFoundException(string.Format("None fixture has been found to be executed in '{0}'",
                                                              folder));
            }
            return files.OrderBy(x => x).ToArray();
        }
        static public string GetNUnit4PowerShellDirectory()
        {
            Uri u = new Uri(Assembly.GetAssembly(typeof(NUnit4PowerShell.PSFixture)).CodeBase);
            string dir = System.IO.Path.GetDirectoryName(u.LocalPath);
            return dir;
        }

        static private string GetFileFullPath(string settingString, bool isMandatoryField)
        {
            string dir = GetNUnit4PowerShellDirectory();

            ConfigurationFileMap configurationFileMap = new ConfigurationFileMap(string.Format(@"{0}\{1}", dir, GetDllConfigurationFileName()));
            Configuration config = ConfigurationManager.OpenMappedMachineConfiguration(configurationFileMap);
            
            string fileNameInSetting = config.AppSettings.Settings[settingString].Value;

            string fullPath = null;
            // If the field is not filled then we return null
            if (fileNameInSetting == null || fileNameInSetting.Trim() == string.Empty)
            {
                if (isMandatoryField)
                {
                    throw new ArgumentException(
                        string.Format("The setting '{0}' in the configuration file has not been filled. Check the file {1}",
                        settingString,
                        AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
                }
                return fullPath;
            }

            // If mock file name is filled, we have to check the file exists
            if (!File.Exists(fileNameInSetting))
            {
                // If the file doesn't exist with check specificly inside the folder defined above
                fullPath = System.IO.Path.Combine(GetPSFixturesFolderPath(), fileNameInSetting);
                if (!File.Exists(fullPath))
                {
                    throw new FileNotFoundException(
                        string.Format(
                            "File containing tests to execute can not be found at the path indicated in the key '{0}' in {1}",
                            settingString,
                            AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
                }
            }
            else
            {
                fullPath = System.IO.Path.GetFullPath(fileNameInSetting);
            }

            return fullPath;
        }

        static public string GetDllConfigurationValue(string name)
        {
            string dir = GetNUnit4PowerShellDirectory();

            ConfigurationFileMap configurationFileMap =
                new ConfigurationFileMap(string.Format(@"{0}\{1}", dir, GetDllConfigurationFileName()));
            Configuration config = ConfigurationManager.OpenMappedMachineConfiguration(configurationFileMap);

            return config.AppSettings.Settings[name].Value;
        }

        internal static bool IsLoggerActivated()
        {
            string dir = GetNUnit4PowerShellDirectory();

            ConfigurationFileMap configurationFileMap = new ConfigurationFileMap(string.Format(@"{0}\{1}", dir, GetDllConfigurationFileName()));
            Configuration config = ConfigurationManager.OpenMappedMachineConfiguration(configurationFileMap);
            string isLoggerActivatedStr = config.AppSettings.Settings["LoggerActivation"].Value;

            if (isLoggerActivatedStr != null)
            {
                bool isLoaggerActivated;
                if (bool.TryParse(isLoggerActivatedStr.Trim(), out isLoaggerActivated))
                {
                    return isLoaggerActivated;
                }
            }
            return false;
        }
    }
}
